package me.ianhe.wedding.socket;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import me.ianhe.wedding.dao.MemoryDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;

/**
 * @author iHelin
 * @date 2019-07-28 15:58
 */
@Component
@ServerEndpoint("/wedding/{weddingId}")
public class WeddingSocketEndPoint {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 解决不能注入问题 添加static
     */
    private static MemoryDao memoryDao;

    @Autowired
    public void setMemoryDao(MemoryDao memoryDao) {
        WeddingSocketEndPoint.memoryDao = memoryDao;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("weddingId") Integer weddingId) {
        memoryDao.addSession(session);
        memoryDao.addSessionAndUser(session, weddingId);
        logger.debug("新连接加入，当前连接数为：{},session id:{}", memoryDao.getSessionCount(), session.getId());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        memoryDao.removeSession(session);
        memoryDao.removeUserRoom(session);
        logger.debug("连接关闭，当前连接数为：{},session id:{}", memoryDao.getSessionCount(), session.getId());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.debug("来自客户端的消息：{},session id:{}", message, session.getId());
    }

    /**
     * 出现错误
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("发生错误，Session ID： {}", session.getId(), error);
    }

    /**
     * 发送消息，实践表明，每次浏览器刷新，session会发生变化。
     */
    private void sendMessage(Session session, Object message) {
        try {
            session.getBasicRemote().sendText(message.toString());
        } catch (IOException e) {
            logger.error("发送消息出错", e);
        }
    }

    /**
     * 给某个房间的所有人发送消息
     *
     * @param message
     */
    public void sendMessagesAll(Object message) {
        Set<Session> sessions = memoryDao.getAllSessions();
        for (Session session : sessions) {
            try {
                session.getAsyncRemote().sendText(objectMapper.writeValueAsString(message));
            } catch (JsonProcessingException e) {
                logger.error("sendMessagesAll", e);
            }
        }
    }

    /**
     * 给某个频道发送消息
     *
     * @param message
     */
    public void sendMessagesChannel(Object message, Integer weddingId) {
        Map<Session, Integer> sessions = memoryDao.getAllMap();
        for (Map.Entry<Session, Integer> entry : sessions.entrySet()) {
            if (entry.getValue().equals(weddingId)) {
                try {
                    entry.getKey().getAsyncRemote().sendText(objectMapper.writeValueAsString(message));
                } catch (JsonProcessingException e) {
                    logger.error("sendMessagesChannel", e);
                }
            }
        }
    }

    /**
     * 给某个房间除自己外发送消息
     *
     * @param currentSession 当前用户
     * @param message        待发送的消息
     */
    private void sendMessagesOther(Session currentSession, Object message) {
        Set<Session> sessions = memoryDao.getAllSessions();
        for (Session session : sessions) {
            if (!session.getId().equals(currentSession.getId())) {
                try {
                    session.getAsyncRemote().sendText(objectMapper.writeValueAsString(message));
                } catch (JsonProcessingException e) {
                    logger.error("sendMessagesOther", e);
                }
            }
        }
    }

}
